package com.ruoyi.app.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.app.annotation.AppSecurity;
import com.ruoyi.app.domain.CustBindCard;
import com.ruoyi.app.domain.CustBindRecord;
import com.ruoyi.app.util.ReqMsg;
import com.ruoyi.app.util.RspMsg;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.vo.CustBindCardLogVo;
import com.ruoyi.bizsys.mapper.BankErrorMapper;
import com.ruoyi.bizsys.service.ICustAndonLogService;
import com.ruoyi.bizsys.service.ICustBankCardService;
import com.ruoyi.bizsys.service.ICustBindCardLogService;
import com.ruoyi.bizsys.service.ICreditApplyService;
import com.ruoyi.business.domain.BindCardStatusReq;
import com.ruoyi.business.service.IBankCardService;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.common.VersionUtils;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.extdata.common.Constants;
import com.ruoyi.system.service.ISysConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * @Author: Jamsnin
 * @Date: 2021/3/10 2:17 下午
 */
@Slf4j
@Api("客户银行卡管理")
@RestController
@RequestMapping("/app/card")
public class BankCardController extends BaseController {

    @Autowired
    ICustBankCardService custBankCardService;

    @Autowired
    ICustBindCardLogService custBindCardLogService;

    @Autowired
    IBankCardService bankCardService;

    @Autowired
    ISysConfigService iSysConfigService;

    @Autowired
    BankErrorMapper bankErrorMapper;

    @Autowired
    ICreditApplyService creditApplyService;

    @Autowired
    ICustAndonLogService iCustAndonLogService;

    private final static String BIND_TRANS_STATUS = "bind_trans_status";

    private final static List<String> TRANS_STATUS_LIST = Arrays.asList("2", "3", "9");

    private final static String LACK_OF_BALANCE = "Card balance insufficient; please ensure above 50 Naira balance and try again";
    private final static String NETWORK_ERROR = "Third-party network error, please try again";
    private final static String CARD_ULTRA_LIMIT = "Bank card withdrawal exceeds the limit; please change the card and try again";
    private final static String CARD_BINDING_FAILED_AGAIN = "Bank card invalid, please change the card and try again";
    private final static String PIN_THE_ULTRA_LIMIT = "The number of PIN entries exceeded the limit. Please try again";
    private final static String CARD_NOT_COMPLETE = "Card binding not completed, please try again";
    private final static String BANK_CARD_INVALID = "Bank card  invalid, please change the card and try again";
    private final static String PAYMENT_TIMEOUT = "Payment timeout, please try again";


    private List<BankError> bankErrorList = null;

    @PostMapping("/auth")
    @AppSecurity
    @ApiOperation("获取绑卡认证url")
    @Log(title = "获取绑卡认证url", businessType = BusinessType.GET)
    public RspMsg bindCardUrl(@Validated @RequestBody ReqMsg reqMsg) {

        //获取有效卡数量
        int bankCardCount = getCustBankCardCardStatus().size();

        List<CustBindCardLog> custBindCardLogList = getCustBindCardLogs();
        int count = (int) custBindCardLogList.stream().filter(p -> TRANS_STATUS_LIST.contains(p.getTransStatus())).count();

        String bankListNums = iSysConfigService.selectConfigByKey("bank_list_nums");

        if ((count + bankCardCount) >= Integer.parseInt(bankListNums)) {
            throw new BusinessException(RspEnmu.BIND_COUNT_LIMIT_OR_PENDING);
        }
        return RspMsg.ok(bankCardService.getBindAuthUrl());

    }

    private void cardStrategyCheck() {
        CustomerInfo customerInfo = getCustomerInfo();
        int bankCardCount = custBankCardService.customerCardAndTransCount(customerInfo.getCustNo());
        int maxLimit = custBankCardService.getCardMaxLimit(customerInfo);
        //超过可绑卡数
        if (bankCardCount >= maxLimit) throw new BusinessException(RspEnmu.BIND_COUNT_LIMIT_OR_PENDING);
    }

    //查询卡片是否有效接口
    private List<CustBankCard> getCustBankCardCardStatus() {
        CustBankCard custBankCard = new CustBankCard();
        custBankCard.setUserId(getUserId());
        custBankCard.setState(Constants.BIZ_STATUS_1);
        custBankCard.setCardStatus("0");
        List<CustBankCard> custBankCardList = custBankCardService.selectCustBankCardList(custBankCard);
        return custBankCardList;
    }

    private List<CustBindCardLog> getCustBindCardLogs() {
        CustBindCardLog custBindCardLog = new CustBindCardLog();
        custBindCardLog.setUserId(getUserId());
        custBindCardLog.setState(Constants.BIZ_STATUS_1);
        List<CustBindCardLog> custBindCardLogList = custBindCardLogService.selectCustBindCardLogList(custBindCardLog);
        return custBindCardLogList;
    }

    private List<CustBindCardLogVo> getCustBindCardLogsVo() {
        CustBindCardLogVo custBindCardLogvo = new CustBindCardLogVo();
        custBindCardLogvo.setUserId(getUserId());
        List<CustBindCardLogVo> custBindCardLogList = custBindCardLogService.selectCustBindCardLogVo(custBindCardLogvo);
        return custBindCardLogList;
    }

    @PostMapping("/list")
    @AppSecurity
    @ApiOperation("查询客户绑定银行卡")
    @Log(title = "查询客户绑定银行卡", businessType = BusinessType.GET)
    public RspMsg getCustBindBank(@RequestBody ReqMsg reqMsg) {
        List<CustBankCard> custBankCardList = getCustBankCards();

        List<CustBindCard> custBindCards = new LinkedList<>();
        custBankCardList.forEach(p -> custBindCards.add(CustBindCard.builder().bankCode(p.getBankCode())
                .cardId(p.getId()).bankName(p.getBankName()).isDefault(p.getIsDefault())
                .cardNumber(StringUtils.strInterval("************" + p.getCardNumber().substring(6)))
                .cardStatus(p.getCardStatus()).build()));

        return RspMsg.ok(custBindCards);
    }

    private List<CustBankCard> getCustBankCards() {
        CustBankCard custBankCard = new CustBankCard();
        custBankCard.setUserId(getUserId());
        custBankCard.setState(BizConstants.BIZ_STATUS_1);
        return custBankCardService.selectCustBankCardList(custBankCard);
    }

    @PostMapping("/default")
    @AppSecurity
    @ApiOperation("设置默认卡")
    @Log(title = "设置默认卡", businessType = BusinessType.UPDATE)
    public RspMsg defaultBindCard(@RequestBody ReqMsg reqMsg) {
        CustBindCard custBindCard = JSON.parseObject(reqMsg.getData().toString(), CustBindCard.class);
        log.info("请求data：{}", JSON.toJSONString(custBindCard));

        if (custBindCard.getCardId() == null || StringUtils.isBlank(custBindCard.getCardNumber())) {
            return RspMsg.fail(RspEnmu.PARAM_CANNOT_NULL);
        }

        CustBankCard custBankCard = custBankCardService.selectCustBankCardById(custBindCard.getCardId());
        if (custBankCard == null || !StringUtils.equals(custBankCard.getCardNumber(), custBankCard.getCardNumber())) {
            return RspMsg.fail(RspEnmu.BIND_BANK_NO_FOUND);
        }

        CustBankCard bankCard = new CustBankCard();
        bankCard.setUserId(getUserId());
        bankCard.setIsDefault("Y");
        bankCard.setState(BizConstants.BIZ_STATUS_1);
        List<CustBankCard> bankCards = custBankCardService.selectCustBankCardList(bankCard);
        if (CollectionUtils.isEmpty(bankCards)) {
            return RspMsg.fail(RspEnmu.BIND_BANK_NO_FOUND);
        }
        bankCard.setId(bankCards.get(0).getId());
        bankCard.setIsDefault("N");
        custBankCardService.updateCustBankCard(bankCard);

        CustBankCard card = new CustBankCard();
        card.setId(custBankCard.getId());
        card.setIsDefault("Y");
        custBankCardService.updateCustBankCard(card);

        return RspMsg.ok();
    }

    @PostMapping("/bind/status")
    @AppSecurity
    @ApiOperation("查询客户绑卡状态")
    @Log(title = "查询客户绑卡状态", businessType = BusinessType.GET)
    public RspMsg getCustBindStatus(@RequestBody ReqMsg reqMsg) {

        BindCardStatusReq bindCardReq = JSON.parseObject(reqMsg.getData().toString(), BindCardStatusReq.class);
        log.info("请求data：{}", JSON.toJSONString(bindCardReq));

        checkAttribute(bindCardReq);

        CustBindCardLog custBindCardLog = new CustBindCardLog();
        custBindCardLog.setUserId(getUserId());
        custBindCardLog.setBindSerialNo(bindCardReq.getBindSerialNo());
        custBindCardLog.setState(BizConstants.BIZ_STATUS_1);
        List<CustBindCardLog> custBindCardLogList = custBindCardLogService.selectCustBindCardLogList(custBindCardLog);
        if (CollectionUtils.isEmpty(custBindCardLogList)) {
            return RspMsg.fail(RspEnmu.BIND_BANK_NO_FOUND);
        }

        String transStatus = custBindCardLogList.get(0).getTransStatus();
        JSONObject transRst = new JSONObject();
        transRst.put("transStatus", transStatus);
        transRst.put("transLabel", getDictLabel(BIND_TRANS_STATUS, transStatus));
        if (StringUtils.equalsAny(transStatus, BizConstants.BIND_CARD_WAIT_CUST_SUBMIT, BizConstants.BIND_CARD_GET_AUTH_URL)) {
            transRst.put("authorizationUrl", custBindCardLogList.get(0).getAuthorizationUrl());
        }

        if (StringUtils.equalsAny(transStatus, BizConstants.BIND_CARD_WAIT_CUST_SUBMIT, BizConstants.BIND_CARD_TRANS_PENDING)) {
            bankCardService.startPolling(custBindCardLogList.get(0));
        }

        return RspMsg.ok(transRst);
    }

    @PostMapping("/bind/cancel")
    @AppSecurity
    @ApiOperation("取消绑卡")
    @Log(title = "取消绑卡", businessType = BusinessType.GET)
    public RspMsg cancelBind(@RequestBody ReqMsg reqMsg) {

        //输入参数  bindSerialNo
        CustBindCardLog custBindCardLog = JSON.parseObject(reqMsg.getData().toString(), CustBindCardLog.class);
        log.info("请求data：{}", JSON.toJSONString(custBindCardLog));


        CustBindCardLog custBindCardLogSelect = new CustBindCardLog();
        custBindCardLogSelect.setUserId(getUserId());
        custBindCardLogSelect.setBindSerialNo(custBindCardLog.getBindSerialNo());
        custBindCardLogSelect.setState(BizConstants.BIZ_STATUS_1);
        List<CustBindCardLog> custBindCardLogList = custBindCardLogService.selectCustBindCardLogList(custBindCardLogSelect);
        if (CollectionUtils.isEmpty(custBindCardLogList)) {
            return RspMsg.fail(RspEnmu.BIND_BANK_NO_FOUND);
        }

        CustBindCardLog bindCardLog = custBindCardLogList.get(0);
        bindCardLog.setTransStatus(BizConstants.BIND_CARD_CANCEL_CUST_SUBMIT);
        bindCardLog.setState(BizConstants.BIZ_STATUS_0);
        custBindCardLogService.updateCustBindCardLog(bindCardLog);

        return RspMsg.ok();
    }

    @PostMapping("/bind/record")
    @AppSecurity
    @ApiOperation("查询绑卡记录")
    @Log(title = "查询绑卡记录", businessType = BusinessType.GET)
    public RspMsg getBindRecord(@RequestBody ReqMsg reqMsg) {
        List<CustBindRecord> custBindRecords = new ArrayList<>();
        List<CustBindCardLogVo> custBindCardLogList = getCustBindCardLogsVo();
        //绑卡异常  判断是否为空
        if (null == bankErrorList) {
            //查询所有错误信息
            bankErrorList = bankErrorMapper.selectList();
        }
        //循环用户绑卡记录
        for (CustBindCardLogVo custBindCardLog : custBindCardLogList) {
            //判断TransStatus 是否等于0
            if (StringUtils.equals(custBindCardLog.getTransStatus(), "0")) {
                //循环错误信息
                for (BankError bankError : bankErrorList) {
                    //判断错误信息不为空
                    if (null != custBindCardLog.getRemark()) {
                        if (custBindCardLog.getRemark().equals(bankError.getRemark())) {
                            custBindCardLog.setRemark(bankError.getPrompt());
                        }
                    }
                }
            }
            if (!(StringUtils.equalsAny(custBindCardLog.getRemark(), LACK_OF_BALANCE, NETWORK_ERROR, CARD_ULTRA_LIMIT,
                    CARD_BINDING_FAILED_AGAIN, PIN_THE_ULTRA_LIMIT, CARD_NOT_COMPLETE, BANK_CARD_INVALID, PAYMENT_TIMEOUT))) {
                custBindCardLog.setRemark("Card binding failed");
            }
            //判断状态是否等于 5，7 相等则直接返回
            if (StringUtils.equalsAny(custBindCardLog.getTransStatus(), "5", "7")) {
                custBindCardLog.setRemark("Bank card exist");
            }
            //拼装参数，返回前端
            custBindRecords.add(CustBindRecord.builder().bindSerialNo(custBindCardLog.getBindSerialNo())
                    .authorizationUrl(custBindCardLog.getAuthorizationUrl()).transMsg(custBindCardLog.getRemark())
                    .transStatus(custBindCardLog.getTransStatus())
                    .createTime(DateFormatUtils.format(custBindCardLog.getCreateTime(), "yyyyMMddHHmmss"))
                    .andonSecond(custBindCardLog.getAndonSecond()).build());
        }
        return RspMsg.ok(custBindRecords);
    }

    @PostMapping("/bind/record/del")
    @AppSecurity
    @ApiOperation("删除绑卡记录")
    @Log(title = "删除绑卡记录", businessType = BusinessType.UPDATE)
    public RspMsg deleteBindRecord(@RequestBody ReqMsg reqMsg) {

        BindCardStatusReq bindCardStatusReq = JSON.parseObject(reqMsg.getData().toString(), BindCardStatusReq.class);
        if (StringUtils.isBlank(bindCardStatusReq.getBindSerialNo())) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }

        CustBindCardLog custBindCardLog = new CustBindCardLog();
        custBindCardLog.setBindSerialNo(bindCardStatusReq.getBindSerialNo());
        List<CustBindCardLog> custBindCardLogList = custBindCardLogService.selectCustBindCardLogList(custBindCardLog);
        if (CollectionUtils.isEmpty(custBindCardLogList)) {
            throw new BusinessException(RspEnmu.BIND_BANK_NO_FOUND);
        }

        custBindCardLog.setId(custBindCardLogList.get(0).getId());
        custBindCardLog.setState(BizConstants.BIZ_STATUS_0);
        custBindCardLogService.updateCustBindCardLog(custBindCardLog);

        return RspMsg.ok();
    }

    @PostMapping("/bank/list")
    @AppSecurity
    @ApiOperation("查询银行列表-payStack")
    @Log(title = "查询银行列表-payStack", businessType = BusinessType.GET)
    public RspMsg getBankList(@RequestBody ReqMsg reqMsg) {
        return RspMsg.ok(bankCardService.getPayStackCode());
    }

    @PostMapping("/bank/list2")
    @AppSecurity
    @ApiOperation("查询银行列表-payStack")
    @Log(title = "查询银行列表-payStack", businessType = BusinessType.GET)
    public RspMsg getBankList2(@RequestBody ReqMsg reqMsg) {
        return RspMsg.ok(bankCardService.getPayStackCode());
    }

}
